Pod Priority and Preemption(Pod优先级和抢占)

本节把priority翻译成优先级,Preemption翻译成抢占。

特性状态: Kubernetes v1.8 alpha

在Kubernetes 1.8或更高版本中,Pods 有priority的概念。priority表示某个Pod相对于其他Pod的重要性。当一个Pod不能被调度时,Scheduler试图抢占(驱逐)较低priority的Pod,从而使调度处于pending状态的Pod成为可能。 在未来的Kubernetes版本中,priority还将影响Node上资源的驱逐排序。

注意:抢占不遵守PodDisruptionBudget;有关详细信息,请参阅 the limitations section

How to use priority and preemption(如何使用优先级和抢占)

要在Kubernetes 1.8中使用priority和preemption,请按照如下步骤操作:

  1. 启用该功能。
  2. 添加一个或多个PriorityClasses。
  3. 创建Pod,并将 PriorityClassName 设为你所添加的PriorityClasses之一。当然,您无需直接创建Pod;通常可将 PriorityClassName 添加到集合对象的Pod模板(如Deployment)。

以下部分提供有关这些步骤的更多信息。

Enabling priority and preemption(启用优先级和抢占)

默认情况下,Kubernetes 1.8中的Pod priority和preemption功能是禁用的。要启用该功能,请为API Server和Scheduler设置此命令行标志:

  1. --feature-gates=PodPriority=true

并为API Server设置此标志:

  1. --runtime-config=scheduling.k8s.io/v1alpha1=true

启用该功能后,您可以创建 PriorityClasses 并创建具有 PriorityClassName 设置的Pods。

如果您尝试过该功能后,决定禁用它,那么您必须删除PodPriority命令行标志或将其设置为false,然后重新启动API Server和Scheduler。禁用该功能后,现有的Pod将保留其priority字段,但禁用preemption,priority字段将被忽略;并且,您不能在新Pod中设置PriorityClassName。

PriorityClass

PriorityClass是一个non-namespaced对象,它定义了从priority class到priority整数值的映射。该名称在PriorityClass对象元数据的 name 字段中指定。该值在必需的 value 字段中指定。value值越大,优先级越高。

PriorityClass对象可以有小于或等于10亿的、任意32位整数值。较大的数字保留给关键系统Pod,这些Pod通常不应该被抢占或被驱逐。 集群管理员应为每个映射创建一个PriorityClass对象。

PriorityClass还有两个可选字段: globalDefaultdescription 。对于未设置 PriorityClassName 的Pod, globalDefault 字段表示该PriorityClass的值。只有一个 globalDefault=true 的PriorityClass能够存在于系统中。如果没有设置了 globalDefault 的PriorityClass,那么,未设置 PriorityClassName 的Pod的优先级为零。

description 字段是一个任意字符串。这是为了告诉集群用户,他们什么时候该使用这个PriorityClass。

注1 :如果升级现有集群并启用此功能,则现有Pod的优先级为零。

注2 :为Pod动态添加 globalDefault=true 的PriorityClass,不会更改现有Pod的优先级。此类PriorityClass的值仅用于添加PriorityClass后创建的Pod。

TODO 注2 原文有点歧义,待测试、改进。

注3 :如果您删除了PriorityClass,则引用该PriorityClass名称的现有Pod将保持不变,但您无法继续创建引用该PriorityClass名称的Pod。

Example PriorityClass

  1. apiVersion: scheduling.k8s.io/v1alpha1
  2. kind: PriorityClass
  3. metadata:
  4. name: high-priority
  5. value: 1000000
  6. globalDefault: false
  7. description: "This priority class should be used for XYZ service pods only."

Pod priority

创建一个或多个PriorityClass之后,可创建Pod,并在其spec中指定其中一个PriorityClass名称。priority admission controller使用 priorityClassName 字段并填充该字段的整数值。如果未找到priority class,则Pod被拒绝。

如下YAML是一个Pod的定义,该Pod使用上述示例中所创建的PriorityClass。priority admission controller检查spec,并将Pod的priority设为1000000。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: nginx
  5. labels:
  6. env: test
  7. spec:
  8. containers:
  9. - name: nginx
  10. image: nginx
  11. imagePullPolicy: IfNotPresent
  12. priorityClassName: high-priority

Preemption(抢占)

当Pods被创建时,它们会进入队列并等待被调度。Scheduler从队列中选择一个Pod,并尝试将其调度到Node上。 如果未能找到满足Pod所有要求的Node,则为处于pending状态的Pod触发preemption逻辑。下面我们称这个处于pending状态的Pod为P。抢占逻辑尝试找到一个Node,在删除一个或多个优先级低于P的Pod后,就能在该Node上调度P。 如果能找到这样的Node,则会从Node中删除一个或多个优先级较低的Pod。 在其删除后,P就能在Node上调度。

Limitations of preemption (alpha version)

Starvation of preempting Pod

当Pod被抢占时,受害者获得了 graceful termination period 。他们有graceful termination period所定义的时长完成工作并退出。如果无法优雅关闭,就会被杀死。这个graceful termination period会在 scheduler抢占Pod的时间点 与 能在Node(N)上调度pending Pod(P)的时间点 之间创建时间间隔。 在此期间,Scheduler会调度其他pending的Pod。当受害者退出或终止时,Scheduler会尝试调度在待处理队列中的Pod,并且在Scheduler将P调度到N之前,可能会将其中的一个或多个考虑并调度到N。在这种情况下,所有的受害者退出,Pod P不再适用于Node N。因此,Scheduler将必须抢占Node N或其他Node上的其他Pod,以便能够调度P。对于第二次和后续的抢占,这种情况可能会再次重复,P可能会在一定时间内无法得到调度。这种情况可能会导致各种集群中的问题,在Pod创建速率较高的集群中尤其成问题。

我们将在Pod preemption的Beta版本中解决这个问题。 provided here(在这里提供了) 我们计划实施的解决方案。

PodDisruptionBudget is not supported(不支持PodDisruptionBudget)

Pod Disruption Budget (PDB) 允许应用程序所有者限制从voluntary disruptions中资源下降的Pod的数量。

然而,在选择preemption的受害者时,alpha版本的preemption并不遵守PDB规则。我们计划在beta版本中添加PDB支持,但即使在beta版中,也只是尽可能地遵守PDB。Scheduler将尝试寻找那些 PDB不会被preemption违反的 受害者,但如果未发现这样的受害者,preemption仍然会发生,优先级较低的Pod将被删除,尽管这会违反PDB。

译者按:PDB简介:http://blog.csdn.net/horsefoot/article/details/76496496

Inter-Pod affinity on lower-priority Pods(低优先级Pod的Inter-Pod 亲和性)

在版本1.8中,只有当该问题的答案为yes时,才将Node视为可抢占:“如果从Node中删除所有优先级低于pending Pod的Pod,就能在该Node上调度pending Pod吗?

注意:抢占并不一定会清除所有优先级较低的Pod。如果删除部分优先级较低的Pod就能调度pending Pod,那么只有一部分优先级较低的Pod会被删除。即使如此,上述问题的答案也必须是yes。否则,则Node不被视为可抢占。

如果pending Pod具有与 Node上一个或多个较低优先级Pod 的inter-pod affinity,则在那些较低优先级Pod缺失的情况下,不能满足 inter-Pod affinity规则。在这种情况下,Scheduler不会抢占Node上的任何Pod。相反,它寻找另一个Node。 Scheduler可能会找到一个合适的Node,又或者它找不到合适的Node。不能保证pending Pod能够被调度。

我们可能会在将来的版本中解决这个问题,但还没有一个明确的计划。我们不会认为它是Beta或GA的阻止者。部分原因是找到满足所有inter-Pod affinity规则的较低优先级的Pod集合,计算代价比较高,并且对抢占逻辑增加了相当大的复杂性。此外,即使preemption保留优先级较低的Pod来满足inter-Pod affinity,较低优先级的Pod也可能被其他Pod稍后抢占,这消除了遵守inter-Pod affinity的复杂逻辑的好处。

我们针对此问题的建议解决方案是仅在相同或更高优先级的Pod上创建inter-Pod affinity。

Cross node preemption(跨Node抢占)

假设Node N正被考虑用于抢占,以便可在N上调度pending Pod P。只有当另一个Node上的Pod被抢占时,P才可能在N上可行。这里有一个例子:

  • Node N正在考虑Pod P。
  • Pod Q在与Node N相同zone中的另一个Node上运行。
  • Pod P与Pod Q具有anit-affinity。
  • Pod P和其他Pod之间没有anti-affinity的情况。
  • 为在Node N上安排Pod P,Pod Q应该被抢占,但是Scheduler不执行跨节点抢占。 所以,Pod P在Node N上被视为unschedulable的。

如果Pod Q从其Node中删除,那么久不违反anti-affinity了,并且Pod P可能会在Node N上进行调度。

如果我们找到某种性能合理的算法,可能会考虑在将来的版本中添加跨Node抢占。在这一点上我们不能作任何承诺,并且跨Node抢占不会被认为是Beta或GA的阻止者。

原文

https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/